home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / os2 / bind493a.zip / res / res_comp.c < prev    next >
C/C++ Source or Header  |  1995-12-06  |  11KB  |  430 lines

  1. /*
  2.  * ++Copyright++ 1985, 1993
  3.  * -
  4.  * Copyright (c) 1985, 1993
  5.  *    The Regents of the University of California.  All rights reserved.
  6.  * 
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in the
  14.  *    documentation and/or other materials provided with the distribution.
  15.  * 3. All advertising materials mentioning features or use of this software
  16.  *    must display the following acknowledgement:
  17.  *     This product includes software developed by the University of
  18.  *     California, Berkeley and its contributors.
  19.  * 4. Neither the name of the University nor the names of its contributors
  20.  *    may be used to endorse or promote products derived from this software
  21.  *    without specific prior written permission.
  22.  * 
  23.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  24.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33.  * SUCH DAMAGE.
  34.  * -
  35.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  36.  * 
  37.  * Permission to use, copy, modify, and distribute this software for any
  38.  * purpose with or without fee is hereby granted, provided that the above
  39.  * copyright notice and this permission notice appear in all copies, and that
  40.  * the name of Digital Equipment Corporation not be used in advertising or
  41.  * publicity pertaining to distribution of the document or software without
  42.  * specific, written prior permission.
  43.  * 
  44.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  45.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  46.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  47.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  48.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  49.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  50.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  51.  * SOFTWARE.
  52.  * -
  53.  * --Copyright--
  54.  */
  55.  
  56. #if defined(LIBC_SCCS) && !defined(lint)
  57. static char sccsid[] = "@(#)res_comp.c    8.1 (Berkeley) 6/4/93";
  58. static char rcsid[] = "$Id: res_comp.c,v 8.3 1995/12/06 20:34:50 vixie Exp $";
  59. #endif /* LIBC_SCCS and not lint */
  60.  
  61. #include <sys/param.h>
  62. #include <netinet/in.h>
  63. #include <arpa/nameser.h>
  64.  
  65. #include <stdio.h>
  66. #include <resolv.h>
  67. #include <ctype.h>
  68.  
  69. #if defined(BSD) && (BSD >= 199103)
  70. # include <unistd.h>
  71. # include <string.h>
  72. #else
  73. # include "../conf/portability.h"
  74. #endif
  75.  
  76. static int    dn_find __P((u_char *exp_dn, u_char *msg,
  77.                  u_char **dnptrs, u_char **lastdnptr));
  78.  
  79. /*
  80.  * Expand compressed domain name 'comp_dn' to full domain name.
  81.  * 'msg' is a pointer to the begining of the message,
  82.  * 'eomorig' points to the first location after the message,
  83.  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  84.  * Return size of compressed name or -1 if there was an error.
  85.  */
  86. int
  87. dn_expand(msg, eomorig, comp_dn, exp_dn, length)
  88.     const u_char *msg, *eomorig, *comp_dn;
  89.     char *exp_dn;
  90.     int length;
  91. {
  92.     register const u_char *cp;
  93.     register char *dn;
  94.     register int n, c;
  95.     char *eom;
  96.     int len = -1, checked = 0;
  97.  
  98.     dn = exp_dn;
  99.     cp = comp_dn;
  100.     eom = exp_dn + length;
  101.     /*
  102.      * fetch next label in domain name
  103.      */
  104.     while (n = *cp++) {
  105.         /*
  106.          * Check for indirection
  107.          */
  108.         switch (n & INDIR_MASK) {
  109.         case 0:
  110.             if (dn != exp_dn) {
  111.                 if (dn >= eom)
  112.                     return (-1);
  113.                 *dn++ = '.';
  114.             }
  115.             if (dn+n >= eom)
  116.                 return (-1);
  117.             checked += n + 1;
  118.             while (--n >= 0) {
  119.                 if (((c = *cp++) == '.') || (c == '\\')) {
  120.                     if (dn + n + 2 >= eom)
  121.                         return (-1);
  122.                     *dn++ = '\\';
  123.                 }
  124.                 *dn++ = c;
  125.                 if (cp >= eomorig)    /* out of range */
  126.                     return (-1);
  127.             }
  128.             break;
  129.  
  130.         case INDIR_MASK:
  131.             if (len < 0)
  132.                 len = cp - comp_dn + 1;
  133.             cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
  134.             if (cp < msg || cp >= eomorig)    /* out of range */
  135.                 return (-1);
  136.             checked += 2;
  137.             /*
  138.              * Check for loops in the compressed name;
  139.              * if we've looked at the whole message,
  140.              * there must be a loop.
  141.              */
  142.             if (checked >= eomorig - msg)
  143.                 return (-1);
  144.             break;
  145.  
  146.         default:
  147.             return (-1);            /* flag error */
  148.         }
  149.     }
  150.     *dn = '\0';
  151.     for (dn = exp_dn; (c = *dn) != '\0'; dn++)
  152.         if (isascii(c) && isspace(c))
  153.             return (-1);
  154.     if (len < 0)
  155.         len = cp - comp_dn;
  156.     return (len);
  157. }
  158.  
  159. /*
  160.  * Compress domain name 'exp_dn' into 'comp_dn'.
  161.  * Return the size of the compressed name or -1.
  162.  * 'length' is the size of the array pointed to by 'comp_dn'.
  163.  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
  164.  * is a pointer to the beginning of the message. The list ends with NULL.
  165.  * 'lastdnptr' is a pointer to the end of the arrary pointed to
  166.  * by 'dnptrs'. Side effect is to update the list of pointers for
  167.  * labels inserted into the message as we compress the name.
  168.  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  169.  * is NULL, we don't update the list.
  170.  */
  171. int
  172. dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
  173.     const char *exp_dn;
  174.     u_char *comp_dn, **dnptrs, **lastdnptr;
  175.     int length;
  176. {
  177.     register u_char *cp, *dn;
  178.     register int c, l;
  179.     u_char **cpp, **lpp, *sp, *eob;
  180.     u_char *msg;
  181.  
  182.     dn = (u_char *)exp_dn;
  183.     cp = comp_dn;
  184.     eob = cp + length;
  185.     lpp = cpp = NULL;
  186.     if (dnptrs != NULL) {
  187.         if ((msg = *dnptrs++) != NULL) {
  188.             for (cpp = dnptrs; *cpp != NULL; cpp++)
  189.                 ;
  190.             lpp = cpp;    /* end of list to search */
  191.         }
  192.     } else
  193.         msg = NULL;
  194.     for (c = *dn++; c != '\0'; ) {
  195.         /* look to see if we can use pointers */
  196.         if (msg != NULL) {
  197.             if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
  198.                 if (cp+1 >= eob)
  199.                     return (-1);
  200.                 *cp++ = (l >> 8) | INDIR_MASK;
  201.                 *cp++ = l % 256;
  202.                 return (cp - comp_dn);
  203.             }
  204.             /* not found, save it */
  205.             if (lastdnptr != NULL && cpp < lastdnptr-1) {
  206.                 *cpp++ = cp;
  207.                 *cpp = NULL;
  208.             }
  209.         }
  210.         sp = cp++;    /* save ptr to length byte */
  211.         do {
  212.             if (c == '.') {
  213.                 c = *dn++;
  214.                 break;
  215.             }
  216.             if (c == '\\') {
  217.                 if ((c = *dn++) == '\0')
  218.                     break;
  219.             }
  220.             if (cp >= eob) {
  221.                 if (msg != NULL)
  222.                     *lpp = NULL;
  223.                 return (-1);
  224.             }
  225.             *cp++ = c;
  226.         } while ((c = *dn++) != '\0');
  227.         /* catch trailing '.'s but not '..' */
  228.         if ((l = cp - sp - 1) == 0 && c == '\0') {
  229.             cp--;
  230.             break;
  231.         }
  232.         if (l <= 0 || l > MAXLABEL) {
  233.             if (msg != NULL)
  234.                 *lpp = NULL;
  235.             return (-1);
  236.         }
  237.         *sp = l;
  238.     }
  239.     if (cp >= eob) {
  240.         if (msg != NULL)
  241.             *lpp = NULL;
  242.         return (-1);
  243.     }
  244.     *cp++ = '\0';
  245.     return (cp - comp_dn);
  246. }
  247.  
  248. /*
  249.  * Skip over a compressed domain name. Return the size or -1.
  250.  */
  251. int
  252. __dn_skipname(comp_dn, eom)
  253.     const u_char *comp_dn, *eom;
  254. {
  255.     register const u_char *cp;
  256.     register int n;
  257.  
  258.     cp = comp_dn;
  259.     while (cp < eom && (n = *cp++)) {
  260.         /*
  261.          * check for indirection
  262.          */
  263.         switch (n & INDIR_MASK) {
  264.         case 0:            /* normal case, n == len */
  265.             cp += n;
  266.             continue;
  267.         case INDIR_MASK:    /* indirection */
  268.             cp++;
  269.             break;
  270.         default:        /* illegal type */
  271.             return (-1);
  272.         }
  273.         break;
  274.     }
  275.     if (cp > eom)
  276.         return (-1);
  277.     return (cp - comp_dn);
  278. }
  279.  
  280. static int
  281. mklower(ch)
  282.     register int ch;
  283. {
  284.     if (isascii(ch) && isupper(ch))
  285.         return (tolower(ch));
  286.     return (ch);
  287. }
  288.  
  289. /*
  290.  * Search for expanded name from a list of previously compressed names.
  291.  * Return the offset from msg if found or -1.
  292.  * dnptrs is the pointer to the first name on the list,
  293.  * not the pointer